package com.example.king.openglenvdemo;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;

import com.example.king.glutils.GlesUtil;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import static android.opengl.GLES20.*;
import static android.opengl.GLUtils.texImage2D;

public class TexturedQuadRenderer implements GLSurfaceView.Renderer {

    private final String mVertexShader =
        "attribute vec4 aPosition;\n" +
        "attribute vec2 a_TexCoord;\n" +
        "varying vec2 v_TexCoord;\n" +
        "void main() {\n" +
        " gl_Position = aPosition;\n" +
        " v_TexCoord = a_TexCoord;\n" +
        "}\n";

    private final String mFragmentShader =
        "precision mediump float;\n" +
        "uniform sampler2D u_Sampler;\n" +
        "varying vec2 v_TexCoord;\n" +
        "void main() {\n" +
        "  gl_FragColor = texture2D(u_Sampler, v_TexCoord);\n" +
        "}\n";


    private Context mContext;

    private int mProgram;

    private int maPositionHandle;
    private int maTexCoordHandle;

    private int uTextureSamplerHandle;

    private final int FLOAT_SIZE_BYTES = 4;
    private final int QUAD_VERTICES_DATA_STRIDE_BYTES = 4 * FLOAT_SIZE_BYTES;
    private final int QUAD_VERTICES_DATA_POS_OFFSET = 0;
    private final int QUAD_VERTICES_DATA_UV_OFFSET = 2;

    private final float[] mPointVerticesData = {
            -0.5f, 0.5f,  0.0f, 1 - 1.0f,//Y轴翻转图片,才能正确显示
            -0.5f, -0.5f, 0.0f, 1 - 0.0f,
            0.5f,  0.5f,  1.0f, 1 - 1.0f,
            0.5f,  -0.5f, 1.0f, 1 - 0.0f
    };

    private FloatBuffer mTriangleVertices;

    private int mTextureID;

    public TexturedQuadRenderer(Context context) {
        this.mContext = context;

        mTriangleVertices = ByteBuffer.allocateDirect(mPointVerticesData.length * FLOAT_SIZE_BYTES)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        mTriangleVertices.put(mPointVerticesData).position(0);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        mProgram = GlesUtil.linkProgram(mVertexShader, mFragmentShader);
        glUseProgram(mProgram);

        maPositionHandle = glGetAttribLocation(mProgram, "aPosition");
        GlesUtil.catchError("aPosition");

        maTexCoordHandle = glGetAttribLocation(mProgram, "a_TexCoord");
        GlesUtil.catchError("a_TexCoord");

        uTextureSamplerHandle = glGetUniformLocation(mProgram, "u_Sampler");

        mTriangleVertices.position(QUAD_VERTICES_DATA_POS_OFFSET);
        GLES20.glVertexAttribPointer(maPositionHandle, 2, GLES20.GL_FLOAT, false,
                QUAD_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
        GLES20.glEnableVertexAttribArray(maPositionHandle);

        mTriangleVertices.position(QUAD_VERTICES_DATA_UV_OFFSET);
        GLES20.glVertexAttribPointer(maTexCoordHandle, 2, GLES20.GL_FLOAT, false,
                QUAD_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
        GLES20.glEnableVertexAttribArray(maTexCoordHandle);


        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);


        final int[] textureObjectIds = new int[1];
        glGenTextures(1, textureObjectIds, 0);
        GlesUtil.catchError("create texture");

        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;

        // Read in the resource
        Bitmap bitmap = BitmapFactory.decodeResource(
                mContext.getResources(), R.drawable.huai_jiu, options);

        if (bitmap == null) {
            glDeleteTextures(1, textureObjectIds, 0);
            return ;
        }

//        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

        // Bind to the texture in OpenGL
        glBindTexture(GLES20.GL_TEXTURE_2D, textureObjectIds[0]);

        glTexParameteri(GLES20.GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GLES20.GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
        glGenerateMipmap(GL_TEXTURE_2D);

        // Recycle the bitmap, since its data has been loaded into
        // OpenGL.
        bitmap.recycle();

        // Unbind from the texture.
        glBindTexture(GL_TEXTURE_2D, 0);

        mTextureID = textureObjectIds[0];
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        glViewport(0, 0, width, height);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        glClear(GL_COLOR_BUFFER_BIT);

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);

        glUniform1i(uTextureSamplerHandle, 0);

        glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
    }
}
